

#include "DBManager/Repository/HDF5/Input/Property/PCOMPGRepository.h"

#include "DBManager/Repository/HDF5/Base/HDF5RepositoryMacro.h"

HDF5_REG_REPOSITORY(PCOMPGRepository)

using namespace SG::DBManager::HDF5;
using namespace SG::DataStructure;
using namespace SG::DataStructure::FEM;
using namespace SG::DataStructure::Common;

// 构造函数实现
PCOMPGRepository::PCOMPGRepository(HDF5Database& database)
    : SG::DBManager::HDF5::MainlyRepositoryBase<MainStruct>(database) {}

void PCOMPGRepository::InitialDatasetInfo() {
  RegisterTableInfo<SG::DataStructure::Common::Id>(
      "/OWN/INDEX/INPUT/PROPERTY/PCOMPG", IndexDataset);
  RegisterTableInfo<NasMainStruct>("/SG/INPUT/PROPERTY/PCOMPG/IDENTITY",
                                   MainDataset);
  RegisterTableInfo<SubStructPLY>("/SG/INPUT/PROPERTY/PCOMPG/PLY",
                                  SubDataset_PLY);
}

void PCOMPGRepository::DumpWriteCahce() {
  auto& writeStorage = this->GetMainCache().m_writeStorage;

  // 1. flag设置为无顺序
  GetMainDatasetInfo().SetIsSequential(false);

  // 主表数据
  std::vector<NasMainStruct> IDENTITYData{};
  // 附表数据
  std::vector<SubStructPLY> subDataPLY;

  // 2. 转换为nastran格式数据
  OwnToNastran(writeStorage, IDENTITYData, subDataPLY);

  // 3. 写出数据至文件
  WriteData(MainDataset, IDENTITYData);
  WriteData(SubDataset_PLY, subDataPLY);

  // 4. 更新Index表
  this->WriteIndexData(this->GetIndexDatasetInfo(), writeStorage);

  // 5. 清空缓存
  writeStorage.clear();
}

std::vector<PCOMPGRepository::DataType>*  PCOMPGRepository::LoadReadCache(std::size_t loadIndex) {
  // 1. 读取范围内主表数据
  std::vector<NasMainStruct> IDENTITYData;
  LoadMainMetadata(loadIndex, IDENTITYData);

  if (IDENTITYData.empty()) {
    return nullptr;
  }

  // 2. 读取范围内附表数据
  std::vector<SubStructPLY> subDataPLY;

  LoadSecondaryMetadata(IDENTITYData, PLY_POS, PLY_LEN, SubDataset_PLY,
                        subDataPLY);

  // 3. 将数据转换为自己的格式放入缓存
  auto* cacheVector = m_cacheHelper.LookupOrCreateVector<DataType> (GetMainCache ().m_readCacheKey, IDENTITYData.size ());
  NastranToOwn(IDENTITYData, subDataPLY, *cacheVector);
  return cacheVector;
}

void PCOMPGRepository::SortData() {
  // 1. 读取主表数据
  std::vector<NasMainStruct> IDENTITYData;
  GetDataset(MainDataset).read(IDENTITYData);

  if (IDENTITYData.empty()) {
    GetMainDatasetInfo().SetIsSequential(true);
    return;
  }

  // 2. 读取附表数据
  std::vector<SubStructPLY> subDataPLY;

  GetDataset(SubDataset_PLY).read(subDataPLY);

  // 3. 将所有数据转换
  std::vector<MainStruct> AllData{};
  NastranToOwn(IDENTITYData, subDataPLY, AllData);

  // 4. 排序
  std::sort(AllData.begin(), AllData.end());

  // 5. 转换回nastran格式
  OwnToNastran(AllData, IDENTITYData, subDataPLY, true);

  // 6. 写出主表数据至文件
  GetDataset(MainDataset).write(IDENTITYData);
  // 7. 写出附表数据至文件
  GetDataset(SubDataset_PLY).write(subDataPLY);

  // 8. 重写索引
  RewriteIndexData(AllData);

  // 9. 设置为已顺序
  GetMainDatasetInfo().SetIsSequential(true);
}

std::vector<PCOMPGRepository::MainStruct> PCOMPGRepository::GetAllData() {
  Sort();

  std::vector<MainStruct> result;

  std::vector<NasMainStruct> IDENTITYData;
  GetDataset(MainDataset).read(IDENTITYData);

  if (IDENTITYData.empty()) {
    return result;
  }

  std::vector<SubStructPLY> subDataPLY;

  GetDataset(SubDataset_PLY).read(subDataPLY);

  // 将所有数据转换
  NastranToOwn(IDENTITYData, subDataPLY, result);

  return result;
}

void PCOMPGRepository::OwnToNastran(
    std::vector<MainStruct>& own, std::vector<NasMainStruct>& _OUT IDENTITYData,
    std::vector<SubStructPLY>& _OUT subDataPLY,

    bool isSort) {
  subDataPLY.clear();

  IDENTITYData.clear();
  IDENTITYData.reserve(own.size());

  // 获取已有数据条数，主要是放在主表的POS字段
  // 如果是重新排序的时候，Pos都是从0 开始的
  size_t countPLY =
      isSort ? 0 : this->GetDatasetInfo(SubDataset_PLY).GetRowCount();

  // OwnIdent 代表咱们自己的数据结构
  // NasIdent 代表nastran的数据结构
  for (auto& OwnIdent : own) {
    // 写入附表
    subDataPLY.insert(subDataPLY.end(), OwnIdent.m_PLYList.begin(),
                      OwnIdent.m_PLYList.end());

    const size_t lenPLY = OwnIdent.m_PLYList.size();

    // 写入IDENTITY
    NasMainStruct NasIdent{};

    NasIdent.PID = OwnIdent.m_id;
    NasIdent.NPLIES = OwnIdent.m_NPLIES;
    NasIdent.Z0 = OwnIdent.m_Z0;
    NasIdent.NSM = OwnIdent.m_NSM;
    NasIdent.SB = OwnIdent.m_SB;
    NasIdent.FT = OwnIdent.m_FT;
    NasIdent.TREF = OwnIdent.m_TREF;
    NasIdent.GE = OwnIdent.m_GE;
    memcpy(NasIdent.MICRO, OwnIdent.m_MICRO, 4);
    NasIdent.DOMAIN_ID = OwnIdent.m_domainId;

    NasIdent.PLY_POS = static_cast<I64>(countPLY);

    NasIdent.PLY_LEN = static_cast<I64>(lenPLY);

    IDENTITYData.emplace_back(NasIdent);

    countPLY += lenPLY;
  }
}

void PCOMPGRepository::NastranToOwn(std::vector<NasMainStruct>& IDENTITYData,
                                    std::vector<SubStructPLY>& subDataPLY,

                                    std::vector<MainStruct>& _OUT own) {
  own.clear();
  own.reserve(IDENTITYData.size());

  // 代表初始的Index 位置,
  // 因为数据有可能是截取了附表的一部分，所有主表中根据POS找的时候需要对应一下，
  // 比如第一个主表数据中POS字段为10000， 附表的vector的数据
  // 就是从附表中的第10000个开始对应的 也就是Index==0的
  // const I64 index = IDENTITYData[0].POS;

  MainStruct const tempown;
  own.resize(IDENTITYData.size(), tempown);

  for (size_t i = 0; i < IDENTITYData.size(); i++) {
    auto& OwnIdent = own[i];
    auto& NasIdent = IDENTITYData[i];

    OwnIdent.m_id = NasIdent.PID;
    OwnIdent.m_NPLIES = NasIdent.NPLIES;
    OwnIdent.m_Z0 = NasIdent.Z0;
    OwnIdent.m_NSM = NasIdent.NSM;
    OwnIdent.m_SB = NasIdent.SB;
    OwnIdent.m_FT = NasIdent.FT;
    OwnIdent.m_TREF = NasIdent.TREF;
    OwnIdent.m_GE = NasIdent.GE;
    memcpy(OwnIdent.m_MICRO, NasIdent.MICRO, 4);
    OwnIdent.m_domainId = NasIdent.DOMAIN_ID;

    if (NasIdent.PLY_LEN != 0) {
      OwnIdent.m_PLYList.assign(
          subDataPLY.begin() + NasIdent.PLY_POS - IDENTITYData[0].PLY_POS,
          subDataPLY.begin() + NasIdent.PLY_POS + NasIdent.PLY_LEN -
              IDENTITYData[0].PLY_POS);
    }
  }
}
